﻿#include "MainGame.h"
#include "ShareComponents.h"
#include "RSManager.h"
#include "QuadTree.h"
#include "Box.h"
#include "FWGame.h"
#include "FWKeyboard.h"
#include "FWGraphic.h"
#include "FWContentManager.h"
#include "Map.h"
#include "Camera.h"

#include "Object.h"
#include "IS.h"
#include "FWTexture.h"
#include <list>
#include "StaticObject.h"
#include "Player.h"
#include "Bridge.h"
#include "BulletManager.h"
#include "Bullet.h"

#include "DefenseCannon.h"
#include "Fire.h"
#include "Sniper.h"
#include "StandSniper.h"
#include "Cannon.h"
#include "Rock.h"
#include "WallTurret.h"
#include "SweptAABB.h"
#include "BackGround.h"
#include "EnemyDie.h"
#include "Barracks.h"
#include "Mechanical.h"
#include "Arm.h"
#include <time.h>
#include "GunWeapon.h"
#define MIN_A   2.3f * 3.14f / 4.0f 
#define MAX_A   6 * 3.14f / 4.0f

MainGame::MainGame(HINSTANCE hIns,char* windowName,int w,int h):FWGame(hIns,windowName,w,h)
{
	D3DXMatrixIdentity(&this->matrix_transform);
}

MainGame::MainGame(FWGame* stateGame) : FWGame(stateGame)
{
	id_scene= MAINGAME;
}

MainGame::~MainGame(void)
{
}

void MainGame::load()
{	
	gl_MainGame =  this;
	_initGameComponents();
	_loadEnemy();
	D3DXVECTOR2 pos = _map->getPlayer().front();	
	//_player = new Player(new Box(D3DXVECTOR2(100,4100), D3DXVECTOR2(0, 0), D3DXVECTOR2(0, 0)));		
	_player = new Player(new Box(pos, D3DXVECTOR2(0, 0), D3DXVECTOR2(0, 0)));		
	
	list<Bridge*> bridge = _map->getStaticBridge();
	for (Bridge* i : bridge)
	{
		_quadTree->insert(i);
	}
	BulletManager::create();	
}

void MainGame::render()
{	
	gl_graphic->clear(D3DCOLOR_XRGB(255,255,255));
	gl_graphic->begin(_cam->getTransformedMatrix());	
	this->_map->render();	
	_bg->render();
	

	_renderEnemies();	

	list<StaticObject*> lBridge = _quadTree->query_staticObj(_cam->getBox());

	for (StaticObject* i : lBridge)
	{
		i->render();
	}
	_player->render();	

	gl_graphic->end();
}

void MainGame::shutdown()
{

}

void MainGame::update(float time)
{			
	Object* max = NULL;
	active.clear();	
	diedObject.clear();

	col_box.clear();
	bound_box.clear();
	bound_box.push_back(_player->getBoundBox());
	col_box.push_back(_player->getCollisionBox());
#pragma region EFFECT
	_bg->update();
#pragma endregion

#pragma region Insert game object to quadtree
	_quadTree->clear();		
	_player->update();	
	_cam->update(_player->getPosForCameraUpdate());
	Box* camera_box = _cam->getBox();
	staticObjectList = _quadTree->query_staticObj(camera_box);
	for (StaticObject* i : staticObjectList)
	{				
		i->update();
	}	
	bullets =  BulletManager::getInstance()->getUsingList();
	for (Bullet* b : bullets)
	{
		if(!SweptAABB::checkAABB(b->getBox(),camera_box))
		{
			BulletManager::getInstance()->collect(b);
			continue;
		}		
		b->update();
		_quadTree->insert(b);
	}	
	//tinh hinh no van dc new. nhung ko có trong worrld 
	for (Object* i : worldObject)
	{
		if(!i->isAlive())
		{
			diedObject.push_back(i);
			continue;
		}		
		_quadTree->insert(i);			
	}
	for (Object* i: diedObject)
	{
		worldObject.remove(i);

		if(i->getObjectType() == ObjAnti_STATIC)
		{
			EnemyDie* x = new EnemyDie(new Box(i->getBox()),Obj_STATIC,EFFECT_EXPLODE1);			
			worldObject.push_back(x);
		}
		if(i->getObjectType() == ObjAnti_DYNAMID)
		{
			EnemyDie* x = new EnemyDie(new Box(i->getBox()),Obj_STATIC,EFFECT_EXPLODE1);			
			worldObject.push_back(x);
		}
		delete i;
	}
	//ở đây là query các object
	active = _quadTree->queryObject(camera_box);
	//ong commit len tui debug chu o day 2 nguoi lam chung 1 viec lau hon :D ok
	float _remainTime;
	float nx, ny;
	Box* b1;
	Box* b2;
#pragma endregion Insert game object to quadtree

#pragma region World
	for (Object*i : active)
	{
		bound_box.push_back(i->getBoundBox());
		col_box.push_back(i->getCollisionBox());
		if(i->getObjectType() == ObjBulletEnemy||i->getObjectType() == ObjBulletPlayer) continue;	
		
		i->update();		
		if(i->getObjectType() == MACHINE) continue;
		//không update đạn		
		collisonObjects = _quadTree->queryObject(i->getBoundBox());		
		for (Object* j : collisonObjects)
		{
			if(j == i || (j->getObjectType() != ObjBulletPlayer)) continue;

			b1 = i->getCollisionBox();
			b2 = j->getCollisionBox();
			

			switch (i->getObjectType())
			{
			case Obj_Weapon:
			case Obj_DYNAMID:
			case ObjAnti_DYNAMID:
				{
					b1->_v -= b2->_v;
					_remainTime = SweptAABB::sweptAABBCheck(b1,b2,nx,ny);
					if(_remainTime < 1.0f) 
					{																				
						i->collide(((Bullet*)j)->getDamage());
						BulletManager::getInstance()->collect((Bullet*)j);						
					}
				}
				break;
				//ok tim ra loi roi :D
			case Obj_STATIC:
			case ObjAnti_STATIC:
				{						
					_remainTime = SweptAABB::sweptAABBCheck(b2,b1,nx,ny);
					if(_remainTime < 1.0f) 
					{																					
						i->collide(((Bullet*)j)->getDamage());
						BulletManager::getInstance()->collect((Bullet*)j);	
					}
				}
				break;
			}
		}
	}
#pragma endregion World

#pragma region Player

	collisonObjects = _quadTree->queryObject(_player->getBoundBox());	

	for (Object* i : collisonObjects)
	{
		b1 = i->getCollisionBox();
		b2 = _player->getCollisionBox();
		switch (i->getObjectType())
		{
		case ObjectType::ObjGrenade:
		case Obj_Anti:
		case ObjAnti_DYNAMID:
			{
				b1->_v -= b2->_v;
				float time = SweptAABB::sweptAABBCheck(b1,b2,nx,ny);
				if(time < 1.0f) 
				{
					_player->collide();
					//:D
				}
			}
			break;
		case ObjAnti_STATIC:
			{				
				_remainTime = SweptAABB::sweptAABBCheck(b2,b1,nx,ny);
				if(_remainTime < 1.0f) 
				{
					//player die here :v
					_player->collide();
				}
			}
			break;
		case ObjBulletEnemy:
			{								
				b1->_v -= b2->_v;
				_remainTime = SweptAABB::sweptAABBCheck(b1,b2,nx,ny);
				if(_remainTime < 1.0f) 
				{					
					_player->collide(((Bullet*)i)->getDamage());
					BulletManager::getInstance()->collect((Bullet*)i);
				}
			}
			break;
		case Obj_Weapon:
			{
				//xử lý kill các đôi tuongj khác tai đây
				GunWeapon* x = (GunWeapon*)i;
				_player->setBulletID(x->getBulletId());
			}
			break;
		}
	}
#pragma endregion Player	
		
}

void MainGame::_loadEnemy()
{
	//player load cho nao vay				
	worldObject = _map->getObject();		
}

void MainGame::_renderEnemies()
{
// 	for (Box* i : bound_box)
// 	{
// 		gl_graphic->tDraw(test,i->getRect(),i->getCenter(),D3DCOLOR_XRGB(0,200,0));
// 	}
	list<Object*> renderList = _quadTree->queryObject(_cam->getBox());
	for (Object* i : renderList)
	{
		i->render();
	}	
// 	for (Box* i : col_box)
// 	{
// 		if(i != NULL)
// 		gl_graphic->tDraw(test,i->getRect(),i->getCenter(),D3DCOLOR_XRGB(255,255,255));
// 	}

}

void MainGame::_initGameComponents()
{										
	this->_map = new Map(MAP5);		
	gl_map =  _map;
	_bg = _map->getBackGround();
	_quadTree = new QuadTree(new Box(D3DXVECTOR2(0,0),D3DXVECTOR2(_map->getWidth() * 32, _map->getHeight() * 32),D3DXVECTOR2(0, 0)));
	_cam = new Camera(0, _map->getWidth() * 32, _map->getHeight() * 32);
	gl_camera = _cam;
	test = gl_content->loadTexture("gr.png");
	grounds = _map->getStaticObjects();
	globe_grounds = grounds;
	for (StaticObject* i : grounds)
	{
		_quadTree->insert(i);
	}
	gl_Quadtree = _quadTree;
}

void MainGame::addWorldObject(Object* obj)
{
	worldObject.push_back(obj);
}

void MainGame::removeWorldObject(Object* obj)
{
	worldObject.remove(obj);
	diedObject.push_back(obj);
}


